home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / SHELLS / SZ2 / GSTRING.IMP < prev    next >
Text File  |  1992-08-31  |  37KB  |  1,033 lines

  1.    {*******************************************************************
  2.  
  3.    GSTRING.IMP
  4.  
  5.    *******************************************************************}
  6.    {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  7.  
  8.                               *** TEXT ***
  9.  
  10.    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}
  11.    {===================================================================
  12.  
  13.    BLANK - TRUE if blank or WhiteSpace
  14.  
  15.    ===================================================================}
  16. function IsBlank ( S : string ) : boolean ;
  17. var
  18.    x                         : byte ;
  19. begin
  20.    IsBlank                   := FALSE ;
  21.    for x := 1 to length ( S ) do
  22.       if S [ x ] <> #32 then EXIT ;
  23.    IsBlank                   := TRUE ;
  24. end ;
  25.    {===================================================================
  26.  
  27.    DUP - Return string of length "Len" of char "Ch"
  28.  
  29.    ===================================================================}
  30. function StrDup ( Ch : char ; len : byte ) : string ;
  31. var
  32.    S                         : string ;
  33. begin
  34.    FillChar ( S [ 1 ] , 255 , Ch ) ;
  35.    S [ 0 ]                   := chr ( len ) ;
  36.    StrDup                    := S ;
  37. end ;
  38.    {===================================================================
  39.  
  40.    CASE (to upper)
  41.  
  42.    ===================================================================}
  43. function StrUpCase ( S : string ) : string ;
  44. var
  45.    b                         : byte ;
  46. begin
  47.    for b := 1 to length ( S ) do
  48.       S [ b ]                := UpCase ( S [ b ] ) ;
  49.    StrUpCase                 := S ;
  50. end ;
  51.    {===================================================================
  52.  
  53.    CASE (to lower)
  54.  
  55.    ===================================================================}
  56. function LoCase ( Ch : char ) : char ;
  57. begin
  58.    if Ch in [ 'A'..'Z' ] then
  59.       LoCase                 := Chr ( Ord ( Ch ) + 32 )
  60.    else
  61.       LoCase                 := Ch ;
  62. end ;
  63.    {===================================================================
  64.  
  65.    CASE (to lower)
  66.  
  67.    ===================================================================}
  68. function StrLoCase ( S : string ) : string ;
  69. var
  70.    x                         : byte ;
  71. begin
  72.    for x := 1 to length ( S ) do
  73.       S [ x ]                := LoCase ( S [ x ] ) ;
  74.    StrLoCase                 := S ;
  75. end ;
  76.    {===================================================================
  77.  
  78.    CAPITALS - 1st letter only
  79.  
  80.    ===================================================================}
  81. function Capitalize ( S : string ) : string ;
  82. var
  83.    x                         : byte ;
  84. begin
  85.    Capitalize                := S ;
  86.    for x := 1 to length ( S ) do
  87.       if S [ x ] in [ 'a'..'z' , 'A'..'Z' ] then
  88.       begin
  89.          S [ x ]             := UpCase ( S [ x ] ) ;
  90.          Capitalize          := S ;
  91.          EXIT ;
  92.       end ;
  93. end ;
  94.    {===================================================================
  95.  
  96.    CAPITAL - all words (after each non-alpha)
  97.  
  98.    ===================================================================}
  99. function InitialCaps ( S : string ) : string ;
  100. var
  101.    DoCap                     : boolean ;
  102.    x                         : byte ;
  103. begin
  104.    DoCap                     := S [ 1 ] in [ 'a'..'z' , 'A'..'Z' ] ;
  105.    for x := 1 to length ( S ) do
  106.    begin
  107.       if DoCap then
  108.       begin
  109.          S [ x ]             := UpCase ( S [ x ] ) ;
  110.          DoCap               := FALSE ;
  111.       end ;
  112.       if not ( S [ x ] in [ 'a'..'z' , 'A'..'Z' ] ) then
  113.          DoCap               := TRUE ;
  114.    end ;
  115.    InitialCaps               := S ;
  116. end ;
  117.    {===================================================================
  118.  
  119.    PAD - increase to length "Len" with leading chars
  120.  
  121.    ===================================================================}
  122. function PadLeft ( S : string ; Ch : char ; Len : byte ) : string ;
  123. begin
  124.    while length ( S ) < len do
  125.       S                      := Ch + S ;
  126.    PadLeft                   := S ;
  127. end ;
  128.    {===================================================================
  129.  
  130.    PAD - increase to length "Len" with trailing chars
  131.  
  132.    ===================================================================}
  133. function PadRight ( S : string ; Ch : char ; Len : byte ) : string ;
  134. begin
  135.    while length ( S ) < len do
  136.       S                      := S + Ch ;
  137.    PadRight                  := S ;
  138. end ;
  139.    {===================================================================
  140.  
  141.    PUT - add leading chars
  142.  
  143.    ===================================================================}
  144. function PutLeft ( S : string ; Ch : char ; Count : byte ) : string ;
  145. begin
  146.    PutLeft                   := StrDup ( Ch , Count ) + S ;
  147. end ;
  148.    {===================================================================
  149.  
  150.    PUT - add trailing chars
  151.  
  152.    ===================================================================}
  153. function PutRight ( S : string ; Ch : char ; Count : byte ) : string ;
  154. begin
  155.    PutRight                  := S + StrDup ( Ch , Count ) ;
  156. end ;
  157.    {===================================================================
  158.  
  159.    COPY - Start to Stop, versus Start & Quantity
  160.           NOTE:  Returns blank on invalid index
  161.    ===================================================================}
  162. function CopyPos ( S : string ; Start , Stop : integer ) : string ;
  163. begin
  164.    CopyPos                   := '' ;
  165.    if Stop >= Start then
  166.       if Start > 0 then
  167.          CopyPos             := Copy ( S ,
  168.                                        Start ,
  169.                                        Stop - Start + 1 ) ;
  170. end ;
  171.    {===================================================================
  172.  
  173.    DELETE - Start to Stop, versus Start & Quantity
  174.             NOTE:  Return original on invalid index
  175.  
  176.    ===================================================================}
  177. function DeletePos ( S : string ; Start , Stop : integer ) : string ;
  178. begin
  179.    if Stop >= Start then
  180.       if Start > 0 then
  181.          delete ( S , Start , Stop - Start + 1 ) ;
  182.    DeletePos                 := S ;
  183. end ;
  184.    {===================================================================
  185.  
  186.    TRUNCATE - Delete from Index to end of string
  187.  
  188.    ===================================================================}
  189. function Truncate ( Source : string ; Index : byte ) : string ;
  190. begin
  191.    Truncate                  := DeletePos ( Source ,
  192.                                             Index ,
  193.                                             length ( Source ) ) ;
  194. end ;
  195.    {===================================================================
  196.  
  197.    MATCH - return position, ignore case
  198.  
  199.    ===================================================================}
  200. function Match ( SubStr , Target : string ) : integer ;
  201. begin
  202.    if length ( SubStr ) > 0 then
  203.       Match                  := pos ( StrUpCase ( SubStr ) ,
  204.                                       StrUpCase ( Target ) )
  205.    else
  206.       Match                  := 0 ;
  207. end ;
  208.    {===================================================================
  209.  
  210.    EXIST - if "SubStr" in "Target"; ignores case
  211.  
  212.    ===================================================================}
  213. function StrExist ( SubStr , Target : string ) : boolean ;
  214. begin
  215.    StrExist                  := Match ( SubStr , Target ) > 0 ;
  216. end ;
  217.    {===================================================================
  218.  
  219.    COUNT - number of occurances
  220.  
  221.    ===================================================================}
  222. function StrCount ( SubStr , S : string ) : integer ;
  223. var
  224.    x                         : integer ;
  225.    Index                     : integer ;
  226. begin
  227.    x                         := 0 ;
  228.    while TRUE do
  229.    begin
  230.       Index                  := Match ( SubStr , S ) ;
  231.       if Index = 0 then
  232.       begin
  233.          StrCount            := x ;
  234.          EXIT ;
  235.       end ;
  236.       inc ( x ) ;
  237.       delete ( S , Index , Length ( SubStr ) ) ;
  238.    end ;
  239. end ;
  240.    {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  241.  
  242.    TRIM
  243.  
  244.    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}
  245.    {===================================================================
  246.  
  247.    LEAD
  248.  
  249.    ===================================================================}
  250. function TrimLeft ( Source , SubStr : string ) : string ;
  251. begin
  252.    SubStr                    := StrUpCase ( SubStr ) ;
  253.    while pos ( SubStr , StrUpCase ( Source ) ) = 1 do
  254.       delete ( Source , 1 , length ( SubStr ) ) ;
  255.    TrimLeft                  := Source ;
  256. end ;
  257.    {===================================================================
  258.  
  259.    TRAIL - ignores case
  260.  
  261.    ===================================================================}
  262. function TrimRight ( Source , SubStr : string ) : string ;
  263. var
  264.    Index                     : integer ;
  265.    Temp                      : string ;
  266. begin
  267.    SubStr                    := StrUpCase ( SubStr ) ;
  268.    while TRUE do
  269.    begin
  270.       Index                  := length ( Source ) - length ( SubStr ) + 1 ;
  271.       temp                   := CopyPos ( Source ,
  272.                                           Index ,
  273.                                           length ( Source ) );
  274.  
  275.       if StrUpCase ( Temp ) <> SubStr then
  276.       begin
  277.          TrimRight           := Source ;
  278.          EXIT ;
  279.       end ;
  280.       Source                 := DeletePos ( Source ,
  281.                                             Index ,
  282.                                             length ( Source ) ) ;
  283.    end ;
  284. end ;
  285.    {===================================================================
  286.  
  287.    LEAD & TRAIL
  288.  
  289.    ===================================================================}
  290. function Trim ( Source , SubStr : string ) : string ;
  291. begin
  292.    Source                    := TrimLeft ( Source , SubStr ) ;
  293.    Source                    := TrimRight ( Source , SubStr ) ;
  294.    Trim                      := Source ;
  295. end ;
  296.    {===================================================================
  297.  
  298.    PREFIX - remove first occurance of "SubStr"
  299.  
  300.    ===================================================================}
  301. function TrimPrefix ( Source , SubStr : string ) : string ;
  302. begin
  303.    if Match ( SubStr , Source ) = 1 then
  304.       delete ( Source , 1 , length ( SubStr ) ) ;
  305.    TrimPrefix                := Source ;
  306. end ;
  307.    {===================================================================
  308.  
  309.    PLUCK - return word by index.  Guaranteed not to have whitespace.
  310.  
  311.    ===================================================================}
  312. function Pluck ( S : string ; Index : byte ) : string ;
  313. var
  314.    count                     : byte ;
  315.    Last                      : byte ;
  316.    temp                      : string ;
  317. begin
  318.    Pluck                     := '' ;
  319.    count                     := 0 ;
  320.    temp                      := '' ;
  321.    S                         := Trim ( S , #32 ) ;  { lead/trail whitespace }
  322.    while TRUE do
  323.    begin
  324.       if count = Index  then
  325.       begin
  326.          Pluck               := temp ;
  327.          EXIT ;
  328.       end ;
  329.       if S = '' then EXIT ;
  330.       if pos ( #32 , S ) = 0 then
  331.          Last                := length ( S )
  332.       else
  333.          Last                := pos ( #32 , S ) - 1 ;
  334.       temp                   := copy ( S , 1 , Last ) ;
  335.       delete ( S , 1 , Last ) ;
  336.       S                      := TrimLeft ( S , #32 ) ; { delete whitespace }
  337.       inc ( count ) ;
  338.    end ;
  339. end ;
  340.    {===================================================================
  341.  
  342.    WORD COUNT - SubStrings separated by whitespace
  343.  
  344.    ===================================================================}
  345. function WordCount ( S : string ) : byte ;
  346. var
  347.    count                     : byte ;
  348. begin
  349.    count                     := 0 ;
  350.    S                         := Trim ( S , #32 ) ;      { delete whitespace }
  351.    while TRUE do
  352.    begin
  353.       if S = '' then
  354.       begin
  355.          WordCount           := count ;
  356.          EXIT ;
  357.       end ;
  358.       if pos ( #32 , S ) = 0 then
  359.          S                   := ''
  360.       else
  361.          delete ( S , 1 , pos ( #32 , S ) - 1 ) ;
  362.       S                      := TrimLeft ( S , #32 ) ; { delete whitespace }
  363.       inc ( count ) ;
  364.    end ;
  365. end ;
  366.   {===================================================================
  367.  
  368.   POS - Index of "Substr" in "Source", from "Start"; ignores case
  369.  
  370.   ===================================================================}
  371. function PosNext ( Substr , Source : string ; Start : byte ) : byte ;
  372. var
  373.    found                     : boolean ;
  374.    Index ,
  375.    j ,
  376.    Limit                     : byte ;
  377. begin
  378.    PosNext                   := 0 ;
  379.    if Source = '' then EXIT ;
  380.    if length ( SubStr ) = 0 then EXIT ;
  381.    if length ( Source ) < length ( SubStr ) then EXIT ;
  382.    Source                    := StrUpCase ( Source ) ;
  383.    SubStr                    := StrUpCase ( SubStr ) ;
  384.    Limit                     := length ( Source ) -
  385.                                 length ( SubStr ) +
  386.                                 1 ;
  387.    if Start < 1 then
  388.       Start                     := 1 ;
  389.    for Index := Start to Limit do
  390.    begin
  391.       found                  := TRUE ;
  392.       J                      := 0 ;
  393.       Repeat
  394.          inc ( j ) ;
  395.          if Source [ Index + j - 1 ] <>
  396.             SubStr [ j ] then
  397.             found            := FALSE ;
  398.       Until ( not found ) or
  399.             ( j >= length ( SubStr ) ) ;
  400.       if found then
  401.       begin
  402.          PosNext             := Index ;
  403.          EXIT ;
  404.       end ;
  405.    end ;
  406. end ;
  407.    {===================================================================
  408.  
  409.    EXTRACT - From "SubStr" to whitespace or end; ignores case
  410.  
  411.    Source = 'hello kbNoKey there'
  412.    SubStr = 'kb'
  413.  
  414.    Extract = 'kbNoKey'
  415.    Source  = 'hello  there'
  416.  
  417.    ===================================================================}
  418. function Extract ( SubStr : string ; VAR Source : string ) : string ;
  419. var
  420.    Start                     : integer ;
  421.    Stop                      : integer ;
  422. begin
  423.    Extract                   := '' ;
  424.    SubStr                    := Trim ( SubStr , #32 ) ;
  425.    if length ( SubStr ) = 0 then EXIT ;
  426.    Start                     := Match ( SubStr , Source ) ;
  427.    if Start <> 1 then
  428.    begin
  429.       SubStr                 := #32 + SubStr ;
  430.       Start                  := Match ( SubStr , Source ) ;
  431.    end ;
  432.    if Start = 0 then EXIT ;
  433.    Stop                      := PosNext ( #32 , Source , Start + 1 ) - 1 ;
  434.    if Stop < 1 then
  435.       Stop                   := length ( Source ) ;
  436.    SubStr                    := CopyPos ( Source ,
  437.                                           Start ,
  438.                                           Stop ) ;
  439.    Extract                   := Trim ( SubStr , #32 ) ;
  440.    Source                    := DeletePos ( Source , Start , Stop ) ;
  441. end ;
  442.    {===================================================================
  443.  
  444.    REPLACE - All occurances of Original with Replacement; ignores case
  445.  
  446.    ===================================================================}
  447. function Replace ( Source , Original , Replacement : string ) : string ;
  448. var
  449.    Index ,
  450.    L ,
  451.    L2                        : byte ;
  452. begin
  453.    Index                     := PosNext ( Original , Source , 1 ) ;
  454.    L                         := length ( Original ) ;
  455.    L2                        := length ( Replacement ) ;
  456.    while Index > 0 do
  457.    begin
  458.       Delete ( Source , Index , L ) ;                           { Cut }
  459.       Insert ( Replacement , Source ,Index ) ;                { Paste }
  460.       Index                  := Index +
  461.                                 1 -
  462.                                 L +
  463.                                 L2 ;
  464.       Index                  := PosNext ( Original , Source , Index ) ;
  465.    end ;
  466.    Replace                   := Source ;
  467. end ;
  468.    {===================================================================
  469.  
  470.    REPLACECHAR - each CHAR in "CharSet" with "Replacement" string
  471.    Note - case sensitive
  472.  
  473.    ===================================================================}
  474. function ReplaceChar ( S , CharSet , Replacement : string ) : string ;
  475. var
  476.    i ,
  477.    L                         : byte ;
  478.    c                         : char ;
  479. begin
  480.    i                         := 1 ;
  481.    L                         := length ( Replacement ) ;
  482.    while i <= length ( S ) do
  483.    begin
  484.       C                      := S [ i ] ;
  485.       if pos ( C , CharSet ) > 0 then
  486.       begin
  487.          delete ( S , i , 1 ) ;
  488.          insert ( Replacement , S , i ) ;
  489.          inc ( i , L ) ;
  490.       end
  491.       else
  492.          inc ( i ) ;
  493.    end ;
  494.    ReplaceChar               := S ;
  495. end ;
  496.    {===================================================================
  497.  
  498.    FILL - replace WhiteSpace with "FillChar" between SearchChars
  499.  
  500.    ===================================================================}
  501. function FillBetween ( S : string ; SearchCh , FillCh : char ) : string ;
  502. var
  503.    x                         : byte ;
  504.    Found                     : boolean ;
  505. begin
  506.    Found                     := FALSE ;
  507.    for x := 1 to length ( S ) do
  508.    begin
  509.       if Found then
  510.       begin
  511.          if S [ x ] = SearchCh then
  512.             Found            := FALSE
  513.          else
  514.             if S [ x ] = #32 then
  515.                S [ x ]       := FillCh ;
  516.       end
  517.       else
  518.          if S [ x ] = SearchCh then
  519.             Found            := TRUE ;
  520.    end ;
  521.    FillBetween               := S ;
  522. end ;
  523.    {===================================================================
  524.  
  525.    COUNT CHAR - number of occurances of "Ch" in "S"
  526.  
  527.    ===================================================================}
  528. function CountCh ( Ch : char ; S : string ) : byte ;
  529. var
  530.    count                     : byte ;
  531. begin
  532.    count                     := 0 ;
  533.    while pos ( Ch , S ) > 0 do
  534.    begin
  535.       inc ( count ) ;
  536.       delete ( S , pos ( Ch , S ) , 1 ) ;
  537.    end ;
  538.    CountCh                 := count ;
  539. end ;
  540.    {===================================================================
  541.  
  542.    WIDE SPACE - Left/Right Justify, Center & Fill-Between by replacing
  543.    "^W" chars with spaces until desired width is reached.
  544.  
  545.    ^W+"Hello"      --> "         Hello"
  546.    "Hello"+^W      --> "Hello         "
  547.    ^W+"Hello"+^W   --> "     Hello    "
  548.    "Hi"+^W+"There" --> "Hi       There"
  549.  
  550.    ===================================================================}
  551. function WideSpace ( S : string ; Code : Char ; NewWidth : byte ) : string ;
  552. var
  553.    Wcount ,
  554.    index                     : byte ;
  555.    {-------------------------------------------------------------------
  556.    -------------------------------------------------------------------}
  557. procedure Run ;
  558. begin
  559.    while TRUE do
  560.    begin
  561.       if length ( S ) >= NewWidth then EXIT ;
  562.       index                  := 1 ;
  563.       while index <= length ( S ) do
  564.       begin
  565.          if length ( S ) >= NewWidth then EXIT ;
  566.          if S [ index ] = Code then
  567.          begin
  568.             insert ( #32 , S , index ) ;
  569.             inc ( index ) ;
  570.          end ;
  571.          inc ( index ) ;
  572.       end ;
  573.    end ;
  574. end ;
  575.    {- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  576.    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
  577. begin
  578.    WideSpace                 := S ;
  579.    Wcount                    := CountCh ( Code , S ) ;
  580.    if Wcount = 0 then EXIT ;
  581.    NewWidth                  := NewWidth + Wcount ;
  582.    Run ;
  583.    while pos ( Code , S ) > 0 do
  584.       delete ( S , pos ( Code , S ) , 1 ) ;
  585.    WideSpace                 := S ;
  586. end ;
  587.    {===================================================================
  588.  
  589.    IBM Graphics/Line-Draw to ASCII
  590.  
  591.    ===================================================================}
  592. procedure ConvertLineDraw ( VAR Ch : char ) ;
  593. begin
  594.    if Ord ( Ch ) and $0080 = 0 then EXIT ;
  595.    case Ch of
  596.    {-------------------------------------------------------------------
  597.    CORNERS
  598.    -------------------------------------------------------------------}
  599.    '⌐' , '¬' , '╖' , '╕' , '╗', '╝' , '╜' , '╛' , '┐', '└' , '╚' , '╔' ,
  600.    '╙' , '╘' , '╒' , '╓' , '┘' , '┌' : Ch := '+' ;
  601.    {-------------------------------------------------------------------
  602.    INTERSECTIONS
  603.    -------------------------------------------------------------------}
  604.    '┴' , '┬' , '├' , '┼' , '╞' , '╟' , '╩' , '╦' , '╠' , '╬' , '╧' ,
  605.    '╨' , '╤' , '╥' , '╫' , '╪' : Ch := '#' ;
  606.    {-------------------------------------------------------------------
  607.    VERTICAL
  608.    -------------------------------------------------------------------}
  609.    '│' , '║' : Ch := '|' ;
  610.    {-------------------------------------------------------------------
  611.    HORIZONTAL
  612.    -------------------------------------------------------------------}
  613.    '─' , '═' : Ch := '-' ;
  614.    {-------------------------------------------------------------------
  615.    BLOCK
  616.    -------------------------------------------------------------------}
  617.    '░' , '▒' , '▓' , '█' , '▄' , '▌' ,'▐' , '▀' , '■' : Ch := '*' ;
  618.    else
  619.       Ch                     := #32 ;
  620.    end ;
  621. end ;
  622.    {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  623.  
  624.                   *** PARAM, SWITCHES & FILENAMES ***
  625.  
  626.    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}
  627.    {===================================================================
  628.  
  629.    Everything from DOS command-line in upper case
  630.  
  631.    ===================================================================}
  632. function CommandLineString : string ;
  633. var
  634.    S                         : string ;
  635.    x                         : byte ;
  636. begin
  637.    S                         := ParamStr ( 1 ) ;
  638.    for x := 2 to ParamCount do
  639.       S                      := S + #32 + ParamStr ( x ) ;
  640.    CommandLineString         := StrUpCase ( S ) ;
  641. end ;
  642.    {===================================================================
  643.  
  644.    PARAM - Just params; ie:  C:>prg "filespec ok /a/b/c" --> "FILESPEC OK"
  645.  
  646.    ===================================================================}
  647. function ParameterString : string ;
  648. begin
  649.    ParameterString           := DeletePos ( CommandLineString ,
  650.                                             pos ( '/' , CommandLineString ) ,
  651.                                             length ( CommandLineString ) ) ;
  652. end ;
  653.    {===================================================================
  654.  
  655.    SWITCH - return switches separated by whitespace
  656.             ie:  C:>prg "filespec ok /a/b/c" --> "/A /B /C"
  657.  
  658.    ===================================================================}
  659. function SwitchString : string ;
  660. var
  661.    S                         : string ;
  662. begin
  663.    S                         := CopyPos ( CommandLineString ,
  664.                                           pos ( '/' , CommandLineString ) ,
  665.                                           length ( CommandLineString ) ) ;
  666.    S                         := Replace ( S , '/' , ' /' ) ;
  667.    SwitchString              := S ;
  668. end ;
  669.    {===================================================================
  670.  
  671.    SWITCH - Return TRUE if "/a" or "a" in C:>prg "filespec ok /a/b/c"
  672.  
  673.    ===================================================================}
  674. function IsSwitch ( S : string ) : boolean ;
  675. var
  676.    Switches                  : string ;
  677.    x                         : byte ;
  678. begin
  679.    IsSwitch                  := TRUE ;
  680.    S                         := StrUpCase ( Replace ( S , '/' , '' ) ) ;
  681.    Switches                  := StrUpCase ( Replace ( SwitchString ,
  682.                                                       '/' ,
  683.                                                       #32 ) ) ;
  684.    for x := 1 to WordCount ( Switches ) do
  685.       if S = Pluck ( Switches , x ) then EXIT ;
  686.    IsSwitch                  := FALSE ;
  687. end ;
  688.    {===================================================================
  689.  
  690.    PARAM - Return TRUE if "OK" or "ok" in  C:>prg "filespec ok /a/b/c"
  691.  
  692.    ===================================================================}
  693. function IsParam ( S : string ) : boolean ;
  694. var
  695.    Params                    : string ;
  696.    x                         : byte ;
  697. begin
  698.    IsParam                   := TRUE ;
  699.    Params                    := StrUpCase ( Replace ( ParameterString ,
  700.                                                       '/' ,
  701.                                                       #32 ) ) ;
  702.    for x := 1 to WordCount ( Params ) do
  703.       if S = Pluck ( Params , x ) then EXIT ;
  704.    IsParam                   := FALSE ;
  705. end ;
  706.    {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  707.  
  708.    NAME
  709.  
  710.    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}
  711.    {===================================================================
  712.  
  713.    DIR - replace directory.  Returns fully-qualified FileSpec.
  714.  
  715.    ===================================================================}
  716. function ReplaceDir ( FileSpec , Dir : string ) : string ;
  717. var
  718.    D                         : DirStr ;
  719.    N                         : NameStr ;
  720.    E                         : ExtStr ;
  721. begin
  722.    ReplaceDir                := '' ;
  723.    FileSpec                  := FExpand ( FileSpec ) ;
  724.    FSplit ( FileSpec , D , N , E ) ;
  725.    if pos ( '.' , E ) = 0 then
  726.       E                      := '.' + E ;
  727.    if Dir [ length ( Dir ) ] <> '\' then
  728.       Dir                    := Dir + '\' ;
  729.    ReplaceDir                := Dir + N + E ;
  730. end ;
  731.    {===================================================================
  732.  
  733.    NAME - replace just name; wildcard if blank
  734.  
  735.    ===================================================================}
  736. function ReplaceName ( FileSpec , Name : string ) : string ;
  737. var
  738.    D                         : DirStr ;
  739.    N                         : NameStr ;
  740.    E                         : ExtStr ;
  741. begin
  742.    ReplaceName               := '' ;
  743.    FSplit ( FileSpec , D , N , E ) ;
  744.    if N = '' then
  745.       N                      := '*' ;
  746.    if pos ( '.' , E ) = 0 then
  747.       E                      := '.' + E ;
  748.    ReplaceName               := D + Name + E ;
  749. end ;
  750.    {===================================================================
  751.  
  752.    EXTENSION - replace if blank or Forced
  753.  
  754.    ===================================================================}
  755. function ReplaceExt ( FileSpec , Ext : string ; Force : boolean ) : string ;
  756. var
  757.    D                         : DirStr ;
  758.    N                         : NameStr ;
  759.    E                         : ExtStr ;
  760. begin
  761.    ReplaceExt                := '' ;
  762.    FileSpec                  := FExpand ( FileSpec ) ;
  763.    FSplit ( FileSpec , D , N , E ) ;
  764.    if N = '' then EXIT ;                                     { blank! }
  765.    if Force or ( E = '' ) then
  766.    begin
  767.       if Ext <> '' then
  768.          if pos ( '.' , Ext ) = 0 then
  769.             Ext              := '.' + Ext ;
  770.       ReplaceExt             := D + N + Ext ;
  771.    end
  772.    else
  773.       ReplaceExt             := FileSpec ;
  774. end ;
  775.    {===================================================================
  776.  
  777.    DIRECTORY - just the drive & directory.
  778.  
  779.    ===================================================================}
  780. function DriveDir ( FileSpec : string ) : string ;
  781. var
  782.    D                         : DirStr ;
  783.    N                         : NameStr ;
  784.    E                         : ExtStr ;
  785. begin
  786.    FileSpec                  := FExpand ( FileSpec ) ;
  787.    FSplit ( FileSpec , D , N , E ) ;
  788.    DriveDir                  := D ;
  789. end ;
  790.    {===================================================================
  791.  
  792.    NAME
  793.  
  794.    ===================================================================}
  795. function NameOnly ( FileSpec : string ) : string ;
  796. var
  797.    D                         : DirStr ;
  798.    N                         : NameStr ;
  799.    E                         : ExtStr ;
  800. begin
  801.    FileSpec                  := FExpand ( FileSpec ) ;
  802.    FSplit ( FileSpec , D , N , E ) ;
  803.    NameOnly                  := N ;
  804. end ;
  805.    {===================================================================
  806.  
  807.    EXTENSION
  808.  
  809.    ===================================================================}
  810. function ExtOnly ( FileSpec : string ) : string ;
  811. var
  812.    D                         : DirStr ;
  813.    N                         : NameStr ;
  814.    E                         : ExtStr ;
  815. begin
  816.    FileSpec                  := FExpand ( FileSpec ) ;
  817.    FSplit ( FileSpec , D , N , E ) ;
  818.    ExtOnly                   := E ;
  819. end ;
  820.    {===================================================================
  821.  
  822.    NAME & EXTENSION
  823.  
  824.    ===================================================================}
  825. function NameExt ( FileSpec : string ) : string ;
  826. var
  827.    D                         : DirStr ;
  828.    N                         : NameStr ;
  829.    E                         : ExtStr ;
  830. begin
  831.    FileSpec                  := FExpand ( FileSpec ) ;
  832.    FSplit ( FileSpec , D , N , E ) ;
  833.    NameExt                   := N + E ;
  834. end ;
  835.    {===================================================================
  836.  
  837.    DRIVE DIR - Uses FExpand to determine current directory
  838.  
  839.    ===================================================================}
  840. function DirOfDrive ( B : byte ) : string ;
  841. begin
  842.    if B > 26 then
  843.       B                      := 0 ;
  844.    if B = 0 then
  845.       DirOfDrive             := FExpand ( '' )
  846.    else
  847.       DirOfDrive             := FExpand ( Chr ( B + 64 ) + ':' ) ;
  848. end ;
  849.    {===================================================================
  850.  
  851.    CALC - find "FileName" in "Path" or "GetEnv('PATH')"
  852.  
  853.    ===================================================================}
  854. function CalcName ( FileName , Path : PathStr ) : PathStr ;
  855. var
  856.    Dir                       : DirStr ;
  857.    Name                      : NameStr ;
  858.    Ext                       : ExtStr ;
  859. begin
  860.    CalcName                  := '' ;
  861.    FileName                  := FExpand ( FileName ) ;
  862.    {- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  863.    DIR - In current or given
  864.    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
  865.    if FileExist ( FileName ) then
  866.    begin
  867.       CalcName               := FileName ;
  868.       EXIT ;
  869.    end ;
  870.    {- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  871.    DIR - On specified "Path"
  872.    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
  873.    FSplit ( FileName , Dir , Name , Ext ) ;
  874.    FileName                  := Name + Ext ;
  875.    FileName                  := FSearch ( FileName , Path ) ;
  876.    if FileName <> '' then
  877.    begin
  878.       CalcName               := FExpand ( FileName ) ;
  879.       EXIT ;
  880.    end ;
  881.    {- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  882.    DIR - Environment "PATH"
  883.    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
  884.    FileName                  := Name + Ext ;
  885.    FileName                  := FSearch ( FileName , GetEnv ( 'PATH' ) ) ;
  886.    if FileName <> '' then
  887.    begin
  888.       CalcName               := FExpand ( FileName ) ;
  889.       EXIT ;
  890.    end ;
  891. end ;
  892.    {|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
  893.  
  894.    FILE
  895.  
  896.    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}
  897.    {===================================================================
  898.  
  899.    FILE EXIST
  900.  
  901.    ===================================================================}
  902. function FileExist ( Path : string ) : boolean ;
  903. var
  904.    SR                        : SearchRec ;
  905. begin
  906.    FileExist                 := FALSE ;                         { set }
  907.    if Path = '' then EXIT ;                           { NUL not valid }
  908.    if pos ( '?' , Path ) > 0 then EXIT ;         { wildcard not valid }
  909.    if pos ( '*' , Path ) > 0 then EXIT ;         { wildcard not valid }
  910.    FindFirst ( Path , 0 , SR ) ;                            { ask DOS }
  911.    FileExist                 := DosError = 0 ;               { result }
  912. end ;
  913.    {===================================================================
  914.  
  915.    EXISTDIR - Return TRUE if the directory exists
  916.  
  917.    ===================================================================}
  918. function DirExist ( DirName : string ) : boolean ;
  919. var
  920.    OldDosError               : integer ;
  921.    SR                        : SearchRec ;
  922. begin
  923.    DirExist                  := FALSE ;
  924.    if pos ( '?' , DirName ) > 0 then EXIT ;
  925.    if pos ( '*' , DirName ) > 0 then EXIT ;
  926.    OldDosError               := DosError ;
  927.    if DirName [ length ( DirName ) ] <> '\' then
  928.       DirName                := DirName + '\' ;
  929.    DirName                   := FExpand ( DirName ) ;
  930.    FindFirst ( DirName + '*.*' , AnyFile , SR ) ;
  931.    DirExist                  := ( DosError = 0 ) and
  932.                                 (
  933.                                   ( SR.Attr and Directory <> 0 ) or
  934.                                   ( length ( DirName ) = 3 )   { root }
  935.                                 ) ;
  936.    DosError                  := OldDosError ;
  937. end ;
  938.    {===================================================================
  939.  
  940.    ERASE
  941.  
  942.    ===================================================================}
  943. function FileErase ( S : string ) : boolean ;
  944. var
  945.    F                         : File ;
  946. begin
  947. {$I-}
  948.    Assign ( F , S ) ;
  949.    Erase ( F ) ;
  950. {$I+}
  951.    FileErase                 := IOresult = 0 ;
  952. end ;
  953.    {===================================================================
  954.  
  955.    RENAME
  956.  
  957.    ===================================================================}
  958. function FileRename ( OldName , NewName : string ) : boolean ;
  959. var
  960.    Ftemp                     : File ;
  961. begin
  962.    SYSTEM.Assign ( Ftemp , OldName ) ;
  963. {$I-}
  964.    SYSTEM.Rename ( Ftemp , NewName ) ;
  965. {$I+}
  966.    FileRename                := IOresult = 0 ;
  967. end ;
  968.    {===================================================================
  969.  
  970.    EXIST:  Match case sensitive KeyString in *.REZ file.
  971.  
  972.    ===================================================================}
  973. function RezExist ( KeyString , FileName : string ) : boolean ;
  974. var
  975.    RezFile                   : PResourceFile ;
  976.    RezStream                 : PStream ;
  977.    i                         : integer ;
  978. begin
  979.    RezExist                  := FALSE ;                   { assume no }
  980.    if not FileExist ( FileName ) then EXIT ;                { no file }
  981.    RezStream                 := New ( PDosStream ,
  982.                                       Init ( FileName ,
  983.                                              stOpen ) ) ;  { instance }
  984.    RezFile                   := New ( PResourceFile ) ;        { init }
  985.    RezFile^.Init ( RezStream ) ;                               { init }
  986.    if RezStream^.Status <> stOK then EXIT ;                { problem! }
  987.    with RezFile^ do
  988.       for i := 0 to Count - 1 do
  989.       begin
  990.          if KeyString = KeyAt ( i ) then
  991.          begin
  992.             RezExist         := TRUE ;                       { gotcha }
  993.             Dispose ( RezFile , Done ) ;      { dumps "RezStream" too }
  994.             EXIT ;                                             { done }
  995.          end ;
  996.       end ;
  997.    Dispose ( RezFile , Done ) ;               { dumps "RezStream" too }
  998. end ;
  999.    {===================================================================
  1000.  
  1001.    GET NAME - return name within width; remove DRIVE:\DIR if same as
  1002.    current dir.
  1003.  
  1004.    filename.ext     C:\..\filename.ext  D:\filename.ext
  1005.    123456789012     123456789012345678  12345678901234
  1006.    12               18                  15
  1007.    ===================================================================}
  1008. function GetName ( S : PathStr ; MaxSize : byte ) : string ;
  1009. var
  1010.    Dir                       : DirStr ;
  1011.    Name                      : NameStr ;
  1012.    Ext                       : ExtStr ;
  1013.    Current                   : DirStr ;
  1014. begin
  1015.    S                         := FExpand ( S ) ;
  1016.    FSplit ( S , Dir , Name , Ext ) ;
  1017.    Current                   := FExpand ( '' ) ;
  1018.    if Dir = Current then
  1019.    begin
  1020.       GetName                := Name + Ext ;            { current dir }
  1021.       EXIT
  1022.    end ;
  1023.    if Dir [ 1 ] = Current [ 1 ] then
  1024.       delete ( Dir , 1 , 2 ) ;                            { dump "x:" }
  1025.    if length ( Dir + Name + Ext ) > MaxSize then
  1026.       if length ( Dir ) > 3 then
  1027.          Dir                 := '\..\' ;
  1028.    S                         := Dir + Name + Ext ;
  1029.    while length ( S ) > MaxSize do                         { failsafe }
  1030.       delete ( S , 1 , 1 ) ;
  1031.    GetName                   := S ;
  1032. end ;
  1033.